package com.gitee.apanlh.web.model;

import com.gitee.apanlh.exp.webfile.WebFileException;
import com.gitee.apanlh.util.base.CollUtils;
import com.gitee.apanlh.util.base.Empty;
import com.gitee.apanlh.util.base.StringUtils;
import com.gitee.apanlh.util.date.DateUtils;
import com.gitee.apanlh.util.encode.Base64Utils;
import com.gitee.apanlh.util.id.IdUtils;
import com.gitee.apanlh.util.io.IOUtils;
import com.gitee.apanlh.util.valid.Assert;
import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.List;

/**	
 * 	基于MultipartFile实现
 * 	
 * 	@author Pan
 */
public class WebFile {
	
	/** 默认存放文件key */
	private static final String DEF_KEY = "file";
	/** 默认分隔符 */ 
	private static final String SPLIT_TAG = "-";
	/** 存放直接传递 */
	private byte[] binary;
	/** 文件值对象 */ 
	private MultiValueMap<String, MultipartFile> files;
	/** 文件个数 */ 
	private int size;
	
	/**	
	 * 	构造函数-默认
	 * 
	 * 	@author Pan
	 */
	WebFile() {
		super();
	}
	
	/**	
	 * 	构造函数-存储文件对象(FormData格式)
	 * 
	 * 	@author Pan
	 * 	@param 	files MultipartFile对象
	 */
	public WebFile(MultiValueMap<String, MultipartFile> files) {
		this.files = files;
		if (this.files == null) {
			this.size = 0;
			return ;
		}
		this.size = files.size();
	}
	
	/**	
	 * 	构造函数-存储文件对象
	 *  <br>自动关闭输入流
	 *  
	 * 	@author Pan
	 * 	@param 	is	输入流
	 */
	public WebFile(InputStream is) {
		this.binary = IOUtils.read(is);
		this.size = 1;
	}
	
	/**	
	 * 	获取文件
	 *  <br>请求类型为application/octet-stream
	 *  	
	 * 	@author Pan
	 * 	@return	byte[]
	 */
	public byte[] getBinaryFile() {
		return this.binary;
	}
	
	/**	
	 * 	获取FormData文件
	 * 	
	 * 	@author Pan
	 * 	@return	MultipartFile
	 */
	public MultipartFile getFile() {
		return getFile(DEF_KEY);
	}
	
	/**	
	 * 	获取文件
	 * 	<br>传递参数无重名情况下返回第一个值
	 * 	
	 * 	@author Pan
	 * 	@param 	key	键
	 * 	@return	MultipartFile
	 */
	public MultipartFile getFile(String key) {
		List<MultipartFile> list = getFiles(key);
		return CollUtils.isEmpty(list) ? null : list.get(0);
	}
	
	/**	
	 * 	获取多个文件
	 * 	<br>传递参数Key为重复
	 * 	
	 * 	@author Pan
	 * 	@param 	key	键
	 * 	@return	List
	 */
	public List<MultipartFile> getFiles(String key) {
		return files.get(key);
	}
	
	/**	
	 * 	获取传递文件Key的个数
	 * 	
	 * 	@author Pan
	 * 	@return	int
	 */
	public int getSize() {
		return this.size;
	}
	
	/**	
	 * 	根据文件生成唯一序列名
	 * 	
	 * 	@author Pan
	 * 	@return	String
	 */
	public String createUniqueFileName() {
		return createUniqueFileName(getFile());
	}
	
	/**	
	 * 	根据文件生成唯一序列名
	 * 	
	 * 	@author Pan
	 * 	@param 	key		键
	 * 	@return	String
	 */
	public String createUniqueFileName(String key) {
		return createUniqueFileName(getFile(key));
	}
	
	/**	
	 * 	根据文件生成唯一序列名
	 * 	<br>日期+ID+后缀
	 * 	
	 * 	@author Pan
	 * 	@param 	file	文件对象
	 * 	@return	String
	 */
	public String createUniqueFileName(MultipartFile file) {
		Assert.isNotNull(file);
		
		String originalFilename = file.getOriginalFilename();
		if (originalFilename == null) {
			return null;
		}
		
		int indexOf = originalFilename.indexOf('.');
		String fileName = indexOf == -1 ? originalFilename : originalFilename.substring(indexOf, originalFilename.length());
		
		StringBuilder sb = new StringBuilder();
		sb.append(DateUtils.currentTime("yyyyMMdd"))
		  .append(SPLIT_TAG)
		  .append(IdUtils.snowFlakeIdStr(30L, 30L))
	  	.append(indexOf == -1 ? originalFilename : fileName);
		return sb.toString();
	}

	/**
	 * 	将文件内容转换为Base64
	 * 	
	 * 	@author Pan
	 * 	@param 	key 键
	 * 	@return	byte[]
	 */
	public byte[] toBase64(String key) {
		MultipartFile file = getFile(key);
		if (file == null) {
			return Empty.arrayByte();
		}
		return Base64Utils.encode(toByte(file));
	}
	
	/**	
	 * 	将文件内容转换为Base64
	 * 
	 * 	@author Pan
	 * 	@param 	key	键
	 * 	@return	String
	 */
	public String toBase64Str(String key) {
		MultipartFile file = getFile(key);
		if (file == null) {
			return null;
		}
		return Base64Utils.encodeToStr(toByte(file));
	}
	
	/**	
	 * 	获取默认文件字节
	 * 	
	 * 	@author Pan
	 * 	@return	byte[]
	 */
	public byte[] toByte() {
		return toByte(DEF_KEY);
	}

	/**	
	 * 	获取文件字节
	 * 	
	 * 	@author Pan
	 * 	@param 	file	文件对象
	 * 	@return	byte[]
	 */
	public byte[] toByte(MultipartFile file) {
		try {
			return file.getBytes();
		} catch (Exception e) {
			throw new WebFileException(StringUtils.format("to byte error cause: {}", e.getMessage()), e);
		}
	}
	
	/**	
	 * 	获取指定文件字节
	 * 	
	 * 	@author Pan
	 * 	@param 	key		键
	 * 	@return	byte[]
	 */
	public byte[] toByte(String key) {
		MultipartFile file = getFile(key);
		if (file == null) {
			return Empty.arrayByte();
		}
		
		try {
			return file.getBytes();
		} catch (Exception e) {
			throw new WebFileException(StringUtils.format("to byte error cause: {}", e.getMessage()), e);
		}
	}
}
